package com.fxc.crowd.mvc.config;

import com.fxc.crowd.constant.CrowdConstant;
import com.fxc.crowd.exception.LoginAcctAlreadyInUseException;
import com.fxc.crowd.exception.LoginAcctAlreadyInUseforUpdateException;
import com.fxc.crowd.exception.LoginFailedException;
import com.fxc.crowd.util.CrowdUtil;
import com.fxc.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ControllerAdvice表示当前类是一个基于注解的异常处理类
 */
@ControllerAdvice
public class CrowdExceptionResolver {

    @ExceptionHandler(value = LoginAcctAlreadyInUseforUpdateException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseException(LoginAcctAlreadyInUseforUpdateException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";

        //返回model对象
        return commonResolve(viewName, exception, request, response);
    }

    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseException(LoginAcctAlreadyInUseException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "admin-add";

        //返回model对象
        return commonResolve(viewName, exception, request, response);
    }

    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginException(LoginFailedException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "admin-login";

        //返回model对象
        return commonResolve(viewName, exception, request, response);
    }

    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveMathException(ArithmeticException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName = "system-error";

        //返回model对象
        return commonResolve(viewName, exception, request, response);
    }

    /**
     * ExceptionHandler将一个具体的异常类型和一个方法相关联起来
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(NullPointerException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //返回失败需要返回的页面
        String viewName = "system-error";

        //返回model对象
        return commonResolve(viewName, exception, request, response);
    }


    private ModelAndView commonResolve(String viewName, Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1. 判断当前请求类型
        boolean judgeResult = CrowdUtil.judegeRequestType(request);
        //2.如果是AJAX 请求
        if (judgeResult) {
            //创建ResultEntity对象
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());

            //创建Gson对象
            Gson gson = new Gson();

            //将ResultEntity对象转换为JSON对象
            String json = gson.toJson(failed);

            //将json字符串作为响应体返回浏览器
            response.getWriter().write(json);

            //由于上面已经通过原生的response对象返回了响应，所以不提供ModelView对象

        }

        //如果不是Ajax请求则创建ModelView对象
        ModelAndView modelAndView = new ModelAndView();

        //将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);

        //设置对应的视图名称
        modelAndView.setViewName(viewName);

        //返回model对象
        return modelAndView;
    }
}
